﻿using System;
using System.IO;
using System.Xml;
using SharpObjects.Configuration;
using SharpObjects.Configuration.ConfigurationProviders;
using SharpObjects.Instantiation;
using SharpObjects.PathMapping;
using SharpObjects.Cryptography;
using SharpObjects.Interfaces;

namespace SharpObjects.Configuration_Test
{
    class SharpConfigurationTest
    {
        static void Main(string[] args)
        {
            Test0();
            Test1();
            Test2();
            Test2a();
            Test3();
            Test4();
            Test5();
            Test6();
            Test7();
        }

        static void Test0()
        {
            string file = "test0.xml";
            XmlDocument doc = new XmlDocument();
            doc.Load(file);

            XmlNodeList selectedNodes = doc.SelectNodes("//my_settings/*");

            XmlCryptography xmlCryptography = new XmlCryptography(doc.DocumentElement, new DefaultPathMapper());

            bool wasModified = false;
            bool isEncryptionEnabled = false;
            bool isEncrypted = false;

            XmlElement element = (XmlElement) doc.SelectSingleNode("//setting1");
            string value1 = xmlCryptography.GetDecryptedXmlElementValue(element, ref wasModified);
            isEncrypted = xmlCryptography.IsElementEncrypted(element);
            isEncryptionEnabled = xmlCryptography.IsEncryptionEnabled(element);

            if(wasModified || isEncrypted || isEncryptionEnabled)
            {
                Console.WriteLine("Error: setting1 should not be encrypted");
            }

            element = (XmlElement) doc.SelectSingleNode("//setting2");
            string value2 = xmlCryptography.GetDecryptedXmlElementValue(element, ref wasModified);
            isEncrypted = xmlCryptography.IsElementEncrypted(element);
            isEncryptionEnabled = xmlCryptography.IsEncryptionEnabled(element);

            if(!wasModified || !isEncrypted || !isEncryptionEnabled)
            {
                Console.WriteLine("ERROR: setting2 must be encrypted");
            }

            Console.WriteLine("setting2: {0}", element.InnerXml);

            element = (XmlElement)doc.SelectSingleNode("//setting3");
            isEncrypted = xmlCryptography.IsElementEncrypted(element);
            isEncryptionEnabled = xmlCryptography.IsEncryptionEnabled(element);
            string value3 = xmlCryptography.GetDecryptedXmlElementValue(element, ref wasModified);
            isEncrypted = xmlCryptography.IsElementEncrypted(element);
            isEncryptionEnabled = xmlCryptography.IsEncryptionEnabled(element);

            Console.WriteLine("setting3: {0}", element.InnerXml);


        }

        static void Test1()
        {
            string fileName = "test1.xml";

            //if (!File.Exists(fullPath))
            {
                using (StreamWriter sw = File.CreateText(fileName))
                {
                    sw.WriteLine("<applicationSettings><mytest3 id=\"bbb\" encryption_key_reference=\"default_key\" is_encrypted=\"false\">some text</mytest3></applicationSettings>");
                }
            }

            IConfigurationProvider configurationProvider = new XmlConfigurationProvider(fileName);

            configurationProvider.AddValue<int>("/applicationSettings", "mytest1", 32, null, "aaa");
            configurationProvider.Save();

            configurationProvider.SetValue("/applicationSettings/mytest1", 41);
            configurationProvider.Save();

            int x = configurationProvider.GetInteger("/applicationSettings/mytest1");

            string path = configurationProvider.CreateEncryptionKey("default.key", overwrite:true);
            configurationProvider.AddEncryptionKey("default_key", path);
            configurationProvider.Save();


            configurationProvider.AddValue<int>("/applicationSettings", "mytest1", 32, "default_key", "bbb");
            configurationProvider.Save();

            string test3 = configurationProvider.GetString("/applicationSettings/mytest3", "not found");

        }

        static void Test2()
        {
            IConfigurationProvider configurationProvider = new XmlConfigurationProvider("test2.xml");

            MyData myData1 = configurationProvider.GetObject<MyData>("/configuration/mydata1");
            MyData myData2 = configurationProvider.GetObject<MyData>("/configuration/mydata2");

            Console.WriteLine(myData2.Message);
        }

        static void Test2a()
        {
            IConfigurationProvider configurationProvider = new XmlConfigurationProvider("test2a.xml");

            MyData myData1 = configurationProvider.GetObject<MyData>("/configuration/data/mydata1");
            MyData2 myData2 = configurationProvider.GetObject<MyData2>("/configuration/data/mydata2");
        }

        static void Test3()
        {
            IConfigurationProvider configurationProvider = new XmlConfigurationProvider("test2.xml");
            configurationProvider.ConfigurationVersion = "production";

            MyData myData1 = configurationProvider.GetObject<MyData>("/configuration/mydata1");
            MyData myData2 = configurationProvider.GetObject<MyData>("/configuration/mydata2");
        }

        static void Test4()
        {
            IConfigurationProvider configurationProvider = new XmlConfigurationProvider("test4.xml");

            MyData myData1 = configurationProvider.GetObject<MyData>("/configuration/mydata1");
            MyData myData2 = configurationProvider.GetObject<MyData>("/configuration/mydata2");
        }

        static void Test5()
        {
            IConfigurationProvider configurationProvider = new XmlConfigurationProvider("test5.xml");

            MyData myData1 = configurationProvider.GetObject<MyData>("/configuration/mydata1");
            MyData myData2 = configurationProvider.GetObject<MyData>("/configuration/mydata2");
        }

        static void Test6()
        {
            //IConfigurationProvider configurationProvider = ConfigurationProviderFactory.GetConfigurationProvider("sharpconfiguration.config", "/configuration");
            //IConfigurationProvider configurationProvider = ConfigurationProviderFactory.GetConfigurationProvider("sharpconfiguration.config");
            IConfigurationProvider configurationProvider = ConfigurationProviderFactory.GetConfigurationProvider();

            string appData = PathMapperFactory.PathMapper.MapApplicationDataPath("aaa");

            MyData myData1 = configurationProvider.GetObject<MyData>("/configuration/mydata1");
            MyData myData2 = configurationProvider.GetObject<MyData>("/configuration/mydata2");
        }

        static void Test7()
        {
            ITypeDescriptor typeDescriptor = new TypeDescriptor()
                                                 {
                                                     AssemblyPath = "SharpObjects.Configuration_Test",
                                                     TypeName = "SharpObjects.Configuration_Test.MyData"
                                                 };

            IInstanceFactory instanceFactory = new InstanceFactory();
            Type type = instanceFactory.GetTypeFromTypeDescriptor(typeDescriptor);


            MyData myData = instanceFactory.CreateObject<MyData>(typeDescriptor);

            if(type == typeDescriptor.Type)
            {
                Console.WriteLine("Types are equal!");
            }        }
    
    }
}
